package handler

import (
	"errors"
	"fmt"
	"net/http"
	"os"
	"ruoyi-go-echo-ddd/internal/application"
	"ruoyi-go-echo-ddd/internal/domain/model"
	"ruoyi-go-echo-ddd/internal/infrastructure/http/request"
	"ruoyi-go-echo-ddd/internal/infrastructure/http/response"
	"ruoyi-go-echo-ddd/internal/infrastructure/utils"
	"strconv"
	"strings"
	"time"

	"github.com/labstack/echo/v4"
	"github.com/rs/zerolog"
	"github.com/spf13/cast"
)

// SysDeptHandler 部门管理控制器
type SysDeptHandler struct {
	deptApp  *application.SysDeptApplication
	tokenApp *application.TokenApplication
}

// NewDeptHandler 系统部门控制器初始化
func NewDeptHandler(d *application.SysDeptApplication, t *application.TokenApplication) *SysDeptHandler {
	return &SysDeptHandler{
		deptApp:  d,
		tokenApp: t,
	}
}

// CheckHandler CheckDept 检查部门是否存在
// @Summary 验证部门是否存在
// @Description 根据部门ID验证部门是否存在
// @Tags 部门管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Param id path string true "部门ID"
// @Success 200 {object} response.Result "部门存在"
// @Success 404 {object} response.Result "部门不存在"
// @Failure 500 {object} response.Result "服务器错误"
// @Router /system/dept/check/exist/{id} [get]
func (handler *SysDeptHandler) CheckHandler(c echo.Context) error {
	id, err := GetSinglePathParam(c, "id")
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}
	// 这里需要验证类型
	deptId, err := strconv.Atoi(id)
	if err != nil {
		response.NewRespCodeMsg(c, 500, "部门ID参数验证失败")
		return nil
	}

	exist, err := handler.deptApp.CheckDept(c, int64(deptId))
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	if exist {
		response.NewRespCodeMsg(c, 200, "部门信息验证通过")
		return nil
	}
	return nil
}

// SaveHandler 保存
// @Summary 新增部门
// @Description 创建新的部门信息
// @Tags 部门管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param dept body model.Dept true "部门信息"
// @Success 200 {object} response.Result{data=model.Dept} "新增成功"
// @Failure 400 {object} response.Result "参数解析错误"
// @Failure 500 {object} response.Result "服务器错误"
// @Router /system/dept [post]
func (handler *SysDeptHandler) SaveHandler(c echo.Context) error {
	var dept *model.Dept
	if err := BindParam(c, &dept); err != nil {
		response.NewRespCodeMsg(c, 500, "部门新增参数解析错误")
		return err
	}

	loginUser, err := handler.tokenApp.GetLoginUser(c)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	if loginUser != nil {
		dept.CreateBy = loginUser.Username
	}

	result, err := handler.deptApp.Save(c, dept)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	response.NewResponse(c, 200, "部门信息新增成功", result)
	return nil
}

// UpdateDept 修改
// @Summary 修改部门
// @Description 修改部门信息
// @Tags 部门管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param dept body model.Dept true "部门信息"
// @Success 200 {object} response.Result{data=model.Dept} "修改成功"
// @Failure 400 {object} response.Result "参数解析错误"
// @Failure 500 {object} response.Result "服务器错误"
// @Router /system/dept [put]
func (handler *SysDeptHandler) UpdateDept(c echo.Context) error {
	var dept *model.Dept
	if err := BindParam(c, &dept); err != nil {
		response.NewRespCodeMsg(c, 500, "部门更新参数解析错误")
		return err
	}

	if dept.Id == 0 {
		response.NewRespCodeMsg(c, 500, "部门ID不能为空")
		return errors.New("部门ID不能为空")
	}

	loginUser, err := handler.tokenApp.GetLoginUser(c)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	if loginUser != nil {
		dept.UpdateBy = loginUser.Username
	}

	result, err := handler.deptApp.Update(c, dept)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}
	response.NewResponse(c, 200, "部门信息更新成功", result)
	return nil
}

// BatchSaveDept 批量新增
// @Summary 部门批量新增
// @Description 部门批量新增
// @Tags 部门管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param list body []model.Dept true "部门集合"
// @Success 200 {object} response.Result{data=[]int64} "批量新增成功"
// @Failure 400 {object} response.Result "参数解析错误"
// @Failure 500 {object} response.Result "服务器错误"
// @Router /system/dept/batchSave [post]
func (handler *SysDeptHandler) BatchSaveDept(c echo.Context) error {
	var list []*model.Dept
	if err := BindParam(c, &list); err != nil {
		response.NewRespCodeMsg(c, 500, "部门批量新增参数解析错误")
		return err
	}

	result, err := handler.deptApp.BatchSave(c, list)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	response.NewResponse(c, 200, "部门信息批量新增成功", result)
	return nil
}

// BatchSaveDeptList 批量新增
// @Summary 部门批量新增
// @Description 部门批量新增
// @Tags 部门管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param list body []request.DeptInsert true "部门集合"
// @Success 200 {object} response.Result{data=[]int64} "批量新增成功"
// @Failure 400 {object} response.Result "参数解析错误"
// @Failure 500 {object} response.Result "服务器错误"
// @Router /system/dept/batchSaveList [post]
func (handler *SysDeptHandler) BatchSaveDeptList(c echo.Context) error {
	var list []*request.DeptInsert
	if err := BindParam(c, &list); err != nil {
		response.NewRespCodeMsg(c, 500, "部门批量新增参数解析错误")
		return err
	}

	zerolog.DefaultContextLogger.Info().Msgf("部门批量新增入参===\n%s", utils.ToJsonFormat(cast.ToSlice(list)))

	result, err := handler.deptApp.BatchSaveByList(c, list)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	zerolog.DefaultContextLogger.Info().Int("批量执行成功条数", len(result)).Msgf("部门新增返回===\n%s", utils.ToJsonFormat(result))

	response.NewResponse(c, 200, "部门信息批量新增成功", result)
	return nil
}

func (handler *SysDeptHandler) ImportData(c echo.Context) error {
	fileMap, err := utils.HandlerEchoUpload(c, "file", utils.TimeNowFormat(""), "")
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	excelAbsPath := fileMap["absPath"]

	// 导入成功后删除excel文件
	defer func(name string) {
		if err = os.Remove(name); err != nil {
			zerolog.DefaultContextLogger.Error().Err(err).Msgf("删除===%s出错", excelAbsPath)
		}
		zerolog.DefaultContextLogger.Info().Msgf("成功删除===%s", excelAbsPath)
	}(excelAbsPath)

	excelData, err := utils.ReadExcelFile(excelAbsPath)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	deptList, err := ConvertToDeptInsert(excelData)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	result, err := handler.deptApp.BatchSaveByList(c, deptList)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	response.NewResponse(c, 200, fmt.Sprintf("部门信息导入成功:%d条", len(result)), result)
	return nil
}

// SelectListHandler 查询部门列表
// @Summary 部门列表查询
// @Description 查询所有部门信息
// @Tags 部门管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param req query string false "部门分页查询参数"
// @Success 200 {object} response.Result{data=[]model.Dept} "查询成功"
// @Failure 500 {object} response.Result "参数解析错误"
// @Router /system/dept/list [get]
func (handler *SysDeptHandler) SelectListHandler(c echo.Context) error {
	req := new(request.DeptPageParam)
	if err := BindParam(c, req); err != nil {
		response.NewRespCodeMsg(c, http.StatusInternalServerError, "部门分页参数解析失败")
		return err
	}

	list, err := handler.deptApp.SelectDeptList(c, req)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}
	response.NewResponse(c, 200, "查询成功", list)
	return nil
}

// SelectByIdHandler 部门查询
// @Summary 部门查询
// @Description 通过ID查询部门
// @Tags 部门管理
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param deptId path string true "部门主键ID"
// @Success 200 {object} response.Result{data=model.Dept} "查询成功"
// @Failure 500 {object} response.Result "参数解析错误"
// @Router /system/dept/{deptId} [get]
func (handler *SysDeptHandler) SelectByIdHandler(c echo.Context) error {
	deptId, err := GetSinglePathParam(c, "deptId")
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	deptInfo, err := handler.deptApp.SelectById(c, cast.ToInt64(deptId))
	if err != nil {
		response.NewRespCodeErr(c, http.StatusInternalServerError, err)
		return err
	}

	response.NewResponse(c, 200, "查询成功", deptInfo)
	return nil
}

// ExcludeDetailHandler 查询部门组级列表
// @Summary 部门查询
// @Description 通过ID查询部门组级列表
// @Tags 部门管理
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param deptId path string true "部门主键ID"
// @Success 200 {object} response.Result{data=[]model.Dept} "查询成功"
// @Failure 500 {object} response.Result "参数解析错误"
// @Router /system/dept/list/exclude/{deptId} [get]
func (handler *SysDeptHandler) ExcludeDetailHandler(c echo.Context) error {
	deptId, err := GetSinglePathParam(c, "deptId")
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}
	id := cast.ToInt64(deptId)
	deptList, err := handler.deptApp.SelectListByDept(c, &model.Dept{})
	if err != nil {
		response.NewRespCodeErr(c, http.StatusInternalServerError, err)
		return err
	}

	var filtered []*model.Dept
	if len(deptList) > 0 {
		for _, dept := range deptList {
			currentId := dept.Id
			if currentId == id {
				continue
			}

			ancestorList := strings.Split(dept.Ancestors, ",")
			if utils.SliceContains(ancestorList, cast.ToString(deptId)) {
				continue
			}
			filtered = append(filtered, dept)
		}
	}

	response.NewResponse(c, 200, "查询成功", filtered)
	return nil
}

type SysDeptPage struct {
	Content []model.Dept `json:"content"`
	Records int64        `json:"records,string"`
	Pages   int64        `json:"pages,string"`
}

// SelectPageHandler 分页处理器
// @Summary 部门分页查询
// @Description 部门分页查询
// @Tags 部门管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param param body request.DeptPageParam true "分页参数"
// @Success 200 {object} SysDeptPage "查询成功"
// @Failure 500 {object} response.Result "参数解析错误"
// @Router /system/dept/page [post]
func (handler *SysDeptHandler) SelectPageHandler(c echo.Context) error {
	req := new(request.DeptPageParam)
	if err := BindParam(c, req); err != nil {
		response.NewRespCodeMsg(c, http.StatusInternalServerError, "部门分页参数解析失败")
		return err
	}
	zerolog.DefaultContextLogger.Info().Msgf("部门分页查询入参===\n%s", utils.ToJsonFormat(req))

	list, total, page, err := handler.deptApp.SelectPage(c, req)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	response.NewResponse(c, 200, "部门分页查询成功", response.NewPageData(list, total, page))
	return nil
}

// BatchDelete 批量删除
// BatchDeleteHandler 部门批量删除
// @Summary 部门批量删除
// @Description 部门批量删除
// @Tags 部门管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param id path string true "英文逗号分割的主键ID"
// @Success 200 {object} response.Result{data=int64} "删除成功"
// @Failure 500 {object} response.Result "参数解析错误"
// @Router /system/dept/batchDel/{id} [delete]
func (handler *SysDeptHandler) BatchDelete(c echo.Context) error {
	ids, err := GlobalDeleteHandler(c, "id")
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	count, err := handler.deptApp.BatchDelete(c, ids)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}
	response.NewResponse(c, 200, "批量删除成功", count)
	return nil
}

func ConvertToDeptInsert(data [][]string) ([]*request.DeptInsert, error) {
	if len(data) == 0 {
		return nil, errors.New("没有可以转换的数据")
	}

	location, err := time.LoadLocation("Asia/Shanghai")
	if err != nil {
		zerolog.DefaultContextLogger.Error().Err(err).Msg("LocalDateTime LoadLocation error")
	}
	var deptInserts []*request.DeptInsert

	for _, row := range data {
		if len(row) != 9 {
			return nil, fmt.Errorf("每行%d个字段数量必须是9", len(row))
		}
		deptInsert := &request.DeptInsert{
			ParentId:   cast.ToInt64(row[0]),
			Ancestors:  row[1],
			DeptName:   row[2],
			OrderNum:   cast.ToInt64(row[3]),
			DeptStatus: row[4],
			CreateBy:   row[5],
			CreateTime: time.Now().In(location),
			UpdateBy:   row[6],
			Remarks:    row[7],
			DelFlag:    row[8],
		}

		deptInserts = append(deptInserts, deptInsert)
	}

	return deptInserts, nil
}

// TreeSelectHandler 查询部门树
// @Summary 查询部门树
// @Description 查询部门树
// @Tags 部门管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Success 200 {object} response.Result{data=[]model.TreeSelect} "查询成功"
// @Router /system/dept/treeSelect [get]
func (handler *SysDeptHandler) TreeSelectHandler(c echo.Context) error {

	deptList, err := handler.deptApp.SelectListByDept(c, &model.Dept{
		DeptStatus: "0",
	})

	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	deptTreeList, err := handler.deptApp.BuildDeptTree(deptList)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	treeSelect := handler.deptApp.BuildDeptTreeSelect(deptTreeList)

	response.NewResponse(c, http.StatusOK, "查询成功", treeSelect)
	return nil
}

// RoleDeptTreeSelectHandler 查询角色部门map
// @Summary 构建部门树
// @Description 构建部门树
// @Tags 部门管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param roleId path string true "角色主键ID"
// @Success 200 {object} response.Result{data=map[string]any} "查询成功"
// @Failure 500 {object} response.Result "参数解析错误"
// @Router /system/dept/roleDeptTreeSelect/{roleId} [get]
func (handler *SysDeptHandler) RoleDeptTreeSelectHandler(c echo.Context) error {
	roleId, err := GetSinglePathParam(c, "roleId")
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	checkedKeys, err := handler.deptApp.SelectListByRoleId(c, cast.ToInt64(roleId))
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	deptList, err := handler.deptApp.SelectListByDept(c, &model.Dept{
		DeptStatus: "0",
	})

	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	dataMap := map[string]any{
		"checkedKeys": checkedKeys,
		"depts":       handler.deptApp.BuildDeptTreeSelect(deptList),
	}
	response.NewResponse(c, http.StatusOK, "查询成功", dataMap)
	return nil
}

// ExportExcelBufferHandler 导出Excel-使用缓冲流
// @Summary 导出Excel
// @Description 导出Excel-使用缓冲流
// @Tags 部门管理
// @Produce application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Success 200 {file} file "Excel文件"
// @Failure 500 {object} response.Result "参数解析错误"
// @Router /system/dept/export [get]
func (handler *SysDeptHandler) ExportExcelBufferHandler(c echo.Context) error {
	data, err := handler.deptApp.SelectAll(c)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}
	headers := []string{"主键ID", "父节点ID", "组级列表", "部门名称", "排序", "部门状态(0正常 1停用)", "创建人", "创建时间", "修改人", "修改时间", "备注信息", "负责人", "手机", "邮箱", "是否删除"}
	return DownloadExcelBuffer(c, "部门信息_"+utils.TimeNowFormat("")+".xlsx", "部门信息", headers, data, true)
}
